# @Time   : 2022/2/21 15:54
# @Author : Fioman
# @Phone  : 13149920693
# @Tips   : Talk is Cheap,Show me the code! ^_^^_^
"""
三拼板的算法识别逻辑和流程
"""
import os
import time

from vision_process.image_process_common import *
from db_tools.db_handler import DbHandler

cp = ConfigParams()
db = DbHandler()

calcArgsNormal = {
    "1": [[2], 17, 11, 8, 18, [20, 40, 60, 120, 150], 0.2],
    "2": [[2], 17, 17, 8, 15, [5, 10, 20, 40], 0],
    "3": [[0], 17, 17, 8, 15, [3, 5, 10, 20, 40, 55], 0],
    "4": [[11], 17, 17, 8, 20, [1, 2, 5, 10, 15], 0],
    "5": [[10], 17, 17, 8, 20, [1, 2, 5], 0],
    # "6": [[1], 17, 17, 8, 15, [20, 40, 60, 80], 0.1] ,
}
tryBeginIndex = 1
upBoxSlice = 0.4633
middleBoxSlice = (0.3, 0.73)
downBoxSlice = 0.54
jointLineExtend = 23  # 单位pix
innerToEdgeThres = 6  # 单位mm
minLineLength = int(20 * cp.mm2pix)  # 线条最短是多少,50个mm
lineLengthMin = 20 * cp.mm2pix
maxLineGap = 5


def get_middle_box_by_up_and_down(midBox, upBox, downBox, totalBoard, height):
    """
    根据上框和下框的位置,以及中框找到的宽度尺寸,寻找中框的位置.
    根据上框的下面两个点的中点,以及下框的上面的两个中点的y坐标之间的平均值,做一条平行线.当成是内板的位置.然后这个平行线.
    这个平行线和左边的以及右边的线都有交点,这个交点当成中框的水平中心线,然后按照左线和右线分别向上和向下延长h/2的距离即可
    :param midBox:
    :param upBox:
    :param downBox:
    :param totalBoard:
    :param height 高度尺寸
    :return:
    """
    h = totalBoard.shape[0]
    middleBoard = totalBoard.copy()[int(middleBoxSlice[0] * h):int(middleBoxSlice[1] * h), :]
    upRightBottom, upLeftBottom = upBox[2:]
    downLeftTop, downRightTop = downBox[:2]
    midBoxCenterY = get_two_points_middle(get_two_points_middle(upRightBottom, upLeftBottom),
                                          get_two_points_middle(downLeftTop, downRightTop))[1]
    # 首先是将midBox的点转换到totalBoard上去
    midBox = [(p[0], p[1] + int(middleBoxSlice[0] * h)) for p in midBox]
    leftTop, rightTop, rightBottom, leftBottom = midBox
    leftK, leftB = get_line_k_and_b(leftTop, leftBottom)
    rightK, rightB = get_line_k_and_b(rightTop, rightBottom)
    # 获取中框左边内框的中点.
    leftLineMidY = midBoxCenterY
    leftLineMidX = leftTop[0] if leftK is None else (leftLineMidY - leftB) / leftK
    # 获取中框右边内框的中点.
    rightLineMidY = midBoxCenterY
    rightLineMidX = rightTop[0] if rightK is None else (rightLineMidY - rightB) / rightK

    # 中点找到了以后,按照这个中点去延长高度的线条
    if leftK is None or rightK is None:
        newLeftTop = [int(leftLineMidX), int(leftLineMidY - height / 2)]
        newLeftBottom = [int(leftLineMidX), int(leftLineMidY + height / 2)]
        newRightTop = [int(rightLineMidX), int(rightLineMidY - height / 2)]
        newRightBottom = [int(rightLineMidX), int(rightLineMidY + height / 2)]
    else:
        yOffsetLeft = abs(height / 2 * np.sin(trans_k_to_rad(leftK)))
        xOffsetLeft = abs(height / 2 * np.cos(trans_k_to_rad(leftK)))
        # xOffsetLeft 规定向上为正的时候为正.
        xOffsetLeft = xOffsetLeft if leftTop[0] - leftBottom[0] > 0 else -xOffsetLeft
        newLeftTop = (int(leftLineMidX + xOffsetLeft), int(leftLineMidY - yOffsetLeft))
        newLeftBottom = (int(leftLineMidX - xOffsetLeft), int(leftLineMidY + yOffsetLeft))

        yOffsetRight = abs(height / 2 * np.sin(trans_k_to_rad(rightK)))
        xOffsetRight = abs(height / 2 * np.cos(trans_k_to_rad(rightK)))
        # xOffsetRight 规定向上为正的时候为正
        xOffsetRight = xOffsetRight if rightTop[0] - rightBottom[0] > 0 else -xOffsetRight
        newRightTop = (int(rightLineMidX + xOffsetRight), int(rightLineMidY - yOffsetRight))
        newRightBottom = (int(rightLineMidX - xOffsetRight), int(rightLineMidY + yOffsetRight))
    totalBoardColor = cv.cvtColor(totalBoard.copy(), cv.COLOR_GRAY2BGR)
    cv.drawContours(totalBoardColor, [np.array(upBox), np.array([newLeftTop, newRightTop, newRightBottom, newLeftBottom]), np.array(downBox)],
                    -1, colorGreen, 3)
    image_show("FindMiddleBoxByUpAndDown", totalBoardColor)
    midBox = [[int(p[0]), int(p[1] - h * middleBoxSlice[0])] for p in [newLeftTop, newRightTop, newRightBottom, newLeftBottom]]
    middleBoardColor = cv.cvtColor(middleBoard.copy(), cv.COLOR_GRAY2BGR)
    cv.drawContours(middleBoardColor, [np.array(midBox)], -1, colorGreen, 3)
    image_show("MiddleBoardFinded", middleBoardColor)
    return midBox


def check_inner_board_3p(board, width, height, calcThresBig, calcThresSmall, boardColor, boardPos, upBox, downBox, innerLine, extendMiddle,
                         isFirstCheck, offset, totalBoard):
    """
    三拼板检测内板的信息的逻辑
    :param board:
    :param width:
    :param height:
    :param calcThresBig:
    :param calcThresSmall:
    :param boardColor:
    :param boardPos:
    :param upBox:
    :param downBox:
    :param innerLine:
    :param extendMiddle:
    :param isFirstCheck:
    :param offset:
    :param totalBoard:
    :return:
    """
    global minLineLength, maxLineGap, lineLengthMin
    boardArea = width * height
    totalHeightPix, totalWidthPix = board.shape[:2]
    totalWidthMm, totalHeightMm = round(totalWidthPix / cp.mm2pix, 2), round(totalHeightPix / cp.mm2pix, 2)
    moveWidthUp = int(totalWidthPix * 0.21)
    moveWidthMid = int(totalWidthPix * 0.3)
    moveHeight = int(totalHeightPix * 0.25)
    res = {
        "result": "error",
        "box": None,
        "info": "",
        "calcSize": (totalWidthMm, totalHeightMm),
        "calcError": (0, 0)
    }

    widthMax = width / cp.mm2pix + calcThresBig
    widthMin = width / cp.mm2pix - calcThresSmall
    heightMax = height / cp.mm2pix + calcThresBig
    heightMin = height / cp.mm2pix - calcThresSmall
    widthMm = width / cp.mm2pix
    heightMm = height / cp.mm2pix
    moveAngleUsed = board.copy()

    try:
        imageH, imageW = moveAngleUsed.shape[:2]
        if boardPos == "up":
            cv.rectangle(moveAngleUsed, (0, 0), (moveWidthUp, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (imageW, 0), (imageW - moveWidthUp, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (0, imageH), (moveWidthUp, imageH - moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (imageW, imageH), (imageW - moveWidthUp, imageH - moveHeight), 0, -1)
        else:
            cv.rectangle(moveAngleUsed, (0, 0,), (moveWidthMid, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (imageW, 0), (imageW - moveWidthMid, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (0, imageH), (moveWidthMid, imageH - moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (imageW, imageH), (imageW - moveWidthMid, imageH - moveHeight), 0, -1)
        image_show("MoveAngle", moveAngleUsed)

        cnts = cv.findContours(moveAngleUsed.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
        cnts = imutils.grab_contours(cnts)
        cntsSorted = sorted(cnts, key=cv.contourArea, reverse=True)
        if len(cntsSorted) == 0:
            res["result"] = "error"
            res["info"] = "{} 框,找内板失败,没有找到任何的轮廓".format(boardPos)
            res["calcSize"] = (totalWidthMm, totalHeightMm)
            res["calcError"] = (round(totalWidthMm - widthMm, 2), round(totalHeightMm - heightMm, 2))
            return res
        cntFindAgain = False  # 是否再找一遍轮廓
        _, (w, h), _ = cv.minAreaRect(cntsSorted[0])
        rectBox = cv.minAreaRect(cntsSorted[0])
        rectBoxPoints = np.int0(cv.boxPoints(rectBox))
        leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectBoxPoints)
        useImage = boardColor.copy()
        cv.drawContours(useImage, [rectBoxPoints], -1, colorGreen, 3)
        image_show("InnerBoardFindedFirst", useImage)
        res["box"] = [leftTop, rightTop, rightBottom, leftBottom]
        widthFinded = round(get_two_point_distance(leftTop, rightTop) / cp.mm2pix, 2)
        heightFinded = round(get_two_point_distance(leftTop, leftBottom) / cp.mm2pix, 2)
        res["calcSize"] = (widthFinded, heightFinded)
        res["calcError"] = round(widthFinded - widthMm, 2), round(heightFinded - heightMm, 2)
        areaFinded = w * h
        if areaFinded < 0.7 * boardArea:
            res["result"] = "error"
            res["info"] = "{}框,找内板失败,找到的内板面积过小".format(boardPos)
            return res
        elif areaFinded > 1.5 * boardArea:
            res["result"] = "error"
            res["info"] = "{}框,找内板失败,找到的内板面积过大".format(boardPos)
            return res
        else:
            # 获取到物料边缘的距离
            innerLine1 = [leftTop, rightTop]
            innerLine2 = [rightTop, rightBottom]
            innerLine3 = [rightBottom, leftBottom]
            innerLine4 = [leftBottom, leftTop]

            # 外城物料区域的四个顶点
            outterLine1 = [(0, 0), (totalWidthPix, 0)]
            outterLine2 = [(totalWidthPix, 0), (totalWidthPix, totalHeightPix)]
            outterLine3 = [(totalWidthPix, totalHeightPix), (0, totalHeightPix)]
            outterLine4 = [(0, totalHeightPix), (0, 0)]

            offsetTop = get_two_line_distance(innerLine1, outterLine1) / cp.mm2pix
            offsetRight = get_two_line_distance(innerLine2, outterLine2) / cp.mm2pix
            offsetBottom = get_two_line_distance(innerLine3, outterLine3) / cp.mm2pix
            offsetLeft = get_two_line_distance(innerLine4, outterLine4) / cp.mm2pix
            print("offsetMm: ({:.2f},{:.2f},{:.2f},{:.2f}),offsetPix: ({},{},{},{})".format(
                offsetTop, offsetRight, offsetBottom, offsetLeft, int(offsetTop * cp.mm2pix), int(offsetRight * cp.mm2pix),
                int(offsetBottom * cp.mm2pix), int(offsetLeft * cp.mm2pix)))
            offsetTopLimit = 10
            offsetBottomLimit = 10
            offsetLeftLimit = 10
            offsetRightLimit = 10
            # 推测第一边.
            if offsetTop < offsetTopLimit or ((not heightMin < heightFinded < heightMax) and (not isFirstCheck)):
                # 推测第一边
                findLineBoard = board.copy()[:int(board.shape[0] * 0.5), :]
                cv.destroyAllWindows()
                image_show("FindTopLineByLine", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.2, 0)
                scharrXY = cv.convertScaleAbs(scharrXY)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYFindTopLine", findLineBoard)
                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                boardShow = boardColor.copy()
                linesList = []
                colorIndex = 0
                for line in lines:
                    x1, y1, x2, y2 = line[0]
                    lineLength = get_two_point_distance((x1, y1), (x2, y2))
                    xMin = totalWidthPix * 0.1
                    xMax = totalWidthPix * 0.9
                    yMin = 10 * cp.mm2pix
                    yMax = totalHeightPix - 10 * cp.mm2pix
                    if abs(y2 - y1) < 10 * cp.mm2pix and abs(x2 - x1) > 5 * cp.mm2pix and yMin < y1 < yMax and yMin < y2 < yMax and \
                            xMin < x1 < xMax and xMin < x2 < xMax and lineLength > lineLengthMin:
                        linesList.append([x1, y1])
                        linesList.append([x2, y2])
                        cv.line(boardShow, (x1, y1), (x2, y2), colorList[colorIndex % 3], 3)
                        colorIndex += 1
                if len(linesList) >= 2:
                    image_show("TopLineFinded", boardShow)
                    cntFindAgain = True
                    if boardPos == "up" and not innerLine:
                        linesListFinal = sorted(linesList, key=lambda x: x[1])
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[1], reverse=True)

                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    y1 = targetLine[0][1]
                    y2 = targetLine[1][1]
                    # 按照最小的那个去截取
                    slicePos = int(min(y1, y2))
                    moveAngleUsed[:slicePos, :] = 0
                    image_show("moveAngleAfterSliceTop", moveAngleUsed)

            # 推测第三边
            if offsetBottom < offsetBottomLimit or ((not heightMin < heightFinded < heightMax) and (not isFirstCheck)):
                yOffset = int(board.shape[0] * 0.5)
                findLineBoard = board.copy()[yOffset:, :]
                cv.destroyAllWindows()
                image_show("FindBottomLineByLine", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.2, 0)
                scharrXY = cv.convertScaleAbs(scharrXY)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYFindBottomLine", findLineBoard)
                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                boardShow = boardColor.copy()
                linesList = []
                colorIndex = 0
                for line in lines:
                    x1, y1, x2, y2 = line[0]
                    y1 += yOffset
                    y2 += yOffset
                    lineLength = get_two_point_distance((x1, y1), (x2, y2))
                    xMin = totalWidthPix * 0.1
                    xMax = totalWidthPix * 0.9
                    yMin = 10 * cp.mm2pix
                    yMax = totalHeightPix - 10 * cp.mm2pix
                    if abs(y2 - y1) < 10 * cp.mm2pix and abs(x2 - x1) > 5 * cp.mm2pix and yMin < y1 < yMax and yMin < y2 < yMax and \
                            xMin < x1 < xMax and xMin < x2 < xMax and lineLength > lineLengthMin:
                        linesList.append([x1, y1])
                        linesList.append([x2, y2])
                        cv.line(boardShow, (x1, y1), (x2, y2), colorList[colorIndex % 3], 3)
                        colorIndex += 1

                if len(linesList) >= 2:
                    image_show("BottomLineFinded", boardShow)
                    cntFindAgain = True
                    if boardPos == "up" or boardPos == "middle" or innerLine:
                        linesListFinal = sorted(linesList, key=lambda x: x[1])
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[1], reverse=True)
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    y1 = targetLine[0][1]
                    y2 = targetLine[1][1]
                    slicePos = int(max(y1, y2))
                    moveAngleUsed[slicePos:, :] = 0
                    image_show("moveAngleAfterSliceBottom", moveAngleUsed)

            # 推测宽度方向的尺寸.
            if widthFinded < widthMin or widthFinded > widthMax:
                # 如果宽度的识别不正确
                if offsetLeft < offsetLeftLimit or innerLine:
                    # 推测左边的那条线
                    findLineBoard = board.copy()[:, :int(board.shape[1] * 0.2)]
                    cv.destroyAllWindows()
                    image_show("findLeftLineByLine", findLineBoard)
                    scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                    scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                    scharrX = cv.convertScaleAbs(scharrX)
                    scharrY = cv.convertScaleAbs(scharrY)
                    scharrXY = cv.addWeighted(scharrX, 0.2, scharrY, 0.1, 0)
                    findLineBoard = scharrXY.copy()
                    image_show("ScharrXYFindLeftLine", findLineBoard)
                    lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                    boardShow = boardColor.copy()
                    linesList = []
                    colorIndex = 0
                    for line in lines:
                        x1, y1, x2, y2 = line[0]
                        lineLength = get_two_point_distance((x1, y1), (x2, y2))
                        xMin = 10 * cp.mm2pix
                        xMax = findLineBoard.shape[1]
                        yMin = totalHeightPix * 0.2
                        yMax = totalHeightPix * 0.8
                        if abs(x2 - x1) < 5 * cp.mm2pix and abs(y2 - y1) > 10 * cp.mm2pix and xMin < x1 < xMax and xMin < x2 < xMax \
                                and yMin < y1 < yMax and yMin < y2 < yMax and lineLength > lineLengthMin:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(boardShow, (x1, y1), (x2, y2), colorList[colorIndex % 3], 3)
                            colorIndex += 1

                    if len(linesList) >= 2:
                        image_show("LeftLineFinded", boardShow)
                        cntFindAgain = True
                        if innerLine:
                            linesListFinal = sorted(linesList, key=lambda x: x[0], reverse=True)
                        else:
                            linesListFinal = sorted(linesList, key=lambda x: x[0])
                        targetLine = [linesListFinal[0], linesListFinal[1]]
                        x1 = targetLine[0][0]
                        x2 = targetLine[1][0]
                        slicePos = int(min(x1, x2))
                        moveAngleUsed[:, :slicePos] = 0
                        image_show("moveAngleAfterSliceLeft", moveAngleUsed)

                # 根据线条推测右边的线
                if offsetRight < offsetRightLimit or innerLine:
                    xOffset = int(board.shape[1] * 0.75)
                    findLineBoard = board.copy()[:, xOffset:]
                    cv.destroyAllWindows()
                    image_show("FindRightLineByLine", findLineBoard)
                    scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                    scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                    scharrX = cv.convertScaleAbs(scharrX)
                    scharrY = cv.convertScaleAbs(scharrY)
                    scharrXY = cv.addWeighted(scharrX, 0.2, scharrY, 0.1, 0)
                    findLineBoard = scharrXY.copy()
                    image_show("ScharrXYFindRightLine", findLineBoard)
                    lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                    boardShow = boardColor.copy()
                    linesList = []
                    colorIndex = 0
                    for line in lines:
                        x1, y1, x2, y2 = line[0]
                        x1 += xOffset
                        x2 += xOffset
                        lineLength = get_two_point_distance((x1, y1), (x2, y2))
                        xMin = boardShow.shape[1] * 0.7
                        xMax = boardShow.shape[1] - 10 * cp.mm2pix
                        yMin = totalHeightPix * 0.2
                        yMax = totalHeightPix * 0.8
                        if abs(x2 - x1) < 5 * cp.mm2pix and abs(y2 - y1) > 10 * cp.mm2pix and xMin < x1 < xMax and xMin < x2 < xMax \
                                and yMin < y1 < yMax and yMin < y2 < yMax and lineLength > lineLengthMin:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(boardShow, (x1, y1), (x2, y2), colorList[colorIndex % 3], 3)
                            colorIndex += 1

                    if len(linesList) >= 2:
                        image_show("RightLineFinded", boardShow)
                        cntFindAgain = True
                        if innerLine:
                            linesListFinal = sorted(linesList, key=lambda x: x[0])
                        else:
                            linesListFinal = sorted(linesList, key=lambda x: x[0], reverse=True)

                        targetLine = [linesListFinal[0], linesListFinal[1]]
                        x1 = targetLine[0][0]
                        x2 = targetLine[1][0]
                        slicePos = int(max(x1, x2))
                        moveAngleUsed[:, slicePos:] = 0
                        image_show("moveAngleAfterSliceRight", moveAngleUsed)

            if cntFindAgain:
                cnts = cv.findContours(moveAngleUsed.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
                cnts = imutils.grab_contours(cnts)
                cntsSorted = sorted(cnts, key=cv.contourArea, reverse=True)
                rectBox = cv.minAreaRect(cntsSorted[0])
                rectBoxPoints = np.int0(cv.boxPoints(rectBox))
                useImage = boardColor.copy()
                cv.drawContours(useImage, [rectBoxPoints], -1, (0, 255, 0), 3)
                image_show("InnerBoardFindedAfterFindLine", useImage)
                leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectBoxPoints)
                res["box"] = leftTop, rightTop, rightBottom, leftBottom
                widthFinded = round(get_two_point_distance(leftTop, rightTop) / cp.mm2pix, 2)
                heightFinded = round(get_two_point_distance(leftTop, leftBottom) / cp.mm2pix, 2)
                res["calcSize"] = widthFinded, heightFinded
                res["calcError"] = round(widthFinded - widthMm, 2), round(heightFinded - heightMm, 2)

            topLineAngle = get_angle_by_k(get_line_k_and_b(leftTop, rightTop)[0])
            if abs(topLineAngle) > 20:
                res["result"] = "error"
                res["info"] = "识别的内框的第一边的角度太大,角度为:{:.2f}".format(topLineAngle)
                res["calcSize"] = (widthFinded, heightFinded)
                res["calcError"] = round(widthFinded - widthMm, 2), round(heightFinded - heightMm, 2)
                return res
            resByExtendFlag = False
            # 再检测一次是否有错误的信息
            innerLine1 = [leftTop, rightTop]
            innerLine3 = [rightBottom, leftBottom]
            offsetTop = get_two_line_distance(innerLine1, outterLine1) / cp.mm2pix
            offsetBottom = get_two_line_distance(innerLine3, outterLine3) / cp.mm2pix

            if extendMiddle:
                if boardPos == "up" and offsetTop > offsetTopLimit and (not heightMin < heightFinded < heightMax) or \
                        (boardPos == "down" and offsetBottom > offsetBottomLimit and (not heightMin < heightFinded < heightMax)):
                    useImage = boardColor.copy()
                    newBox = get_new_box_by_edge_and_height([leftTop, rightTop, rightBottom, leftBottom], height, boardPos, useImage)
                    if newBox is not None:
                        resByExtendFlag = True
                        res["box"] = newBox
                        leftTop, rightTop, rightBottom, leftBottom = newBox
                        widthFinded = round(get_two_point_distance(leftTop, rightTop) / cp.mm2pix, 2)
                        heightFinded = round(get_two_point_distance(leftTop, leftBottom) / cp.mm2pix, 2)
                        res["calcSize"] = widthFinded, heightFinded
                        res["calcError"] = round(widthFinded - widthMm, 2), round(heightFinded - heightMm, 2)
                        res["info"] = "识别成功,通过第一边推测中缝." if boardPos == "up" else "识别成功,通过第三边推测中缝."
                        useImage = boardColor.copy()
                        cv.drawContours(useImage, [np.array(newBox)], -1, colorGreen, 3)
                        image_show("InnerBoardFindedByExtendForMiddle", useImage)

            if widthMin < widthFinded < widthMax and ( not heightMin < heightFinded < heightMax) and boardPos == "middle":
                # 如果中间的框没有找到,并且宽度是对的,高度没有找对.这个时候,可以根据上框和下框,以及高度,推测中间的框的位置.
                newBox = get_middle_box_by_up_and_down([leftTop, rightTop, rightBottom, leftBottom], upBox, downBox, totalBoard, height)
                leftTop, rightTop, rightBottom, leftBottom = newBox
                res["box"] = newBox
                widthFinded = get_two_point_distance(leftTop, rightTop)/cp.mm2pix
                heightFinded = get_two_point_distance(leftTop, leftBottom)/cp.mm2pix
                res["calcSize"] = round(widthFinded, 2), round(heightFinded, 2)
                res["calcError"] = round(widthFinded - widthMm, 2), round(heightFinded - heightMm, 2)
                res["info"] = "识别成功,通过上下两框推测出中间框"
                resByExtendFlag = True

            if isFirstCheck:
                if widthFinded < widthMin or heightFinded < heightMin:
                    res["result"] = "small"
                    res["info"] = "{}框,识别尺寸过小,识别尺寸:{},误差:{}".format(boardPos, res["calcSize"], res["calcError"])
                    return res
                if widthFinded > widthMax or heightFinded > heightMax:
                    res["result"] = "big"
                    res["info"] = "{}框,识别尺寸过大,识别尺寸:{},误差:{}".format(boardPos, res["calcSize"], res["calcError"])
                    return res
            else:
                if widthFinded < widthMin or widthFinded > widthMax:
                    otherLineIsOk, newBox = check_other_line_is_ok(board, res["box"], offset, "24", width, boardPos)
                    if otherLineIsOk:
                        res["box"] = newBox
                        resByExtendFlag = True
                        leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(newBox)
                        widthFinded = get_two_point_distance(leftTop, rightTop)/cp.mm2pix
                        heightFinded = get_two_point_distance(leftTop, leftBottom)/cp.mm2pix
                        res["calcSize"] = round(widthFinded, 2), round(heightFinded, 2)
                        res["calcError"] = round(widthFinded - widthMm, 2), round(heightFinded - heightMm, 2)
                        res["info"] = "识别成功,2,4边通过一边推测另外一边."
                        useImage = boardColor.copy()
                        cv.drawContours(useImage, [np.array(newBox)], -1, colorGreen, 3)
                        image_show("InnerBoardFindedByCalc24", useImage)
                    else:
                        if widthFinded < widthMin:
                            res["result"] = "small"
                            res["info"] = "识别的宽度过小,识别尺寸:{},识别误差:{}".format(res["calcSize"], res["calcError"])
                            return res
                        if widthFinded > widthMax:
                            res["result"] = "big"
                            res["info"] = "识别的宽度过大,识别尺寸:{},识别误差:{}".format(res["calcSize"], res["calcError"])
                            return res
                if heightFinded < heightMin or heightFinded > heightMax:
                    otherLineIsOk, newBox = check_other_line_is_ok(board, res["box"], offset, "13", height, boardPos)
                    if otherLineIsOk:
                        res["box"] = newBox
                        resByExtendFlag = True
                        leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(newBox)
                        widthFinded = get_two_point_distance(leftTop, rightTop)/cp.mm2pix
                        heightFinded = get_two_point_distance(leftTop, leftBottom)/cp.mm2pix
                        res["calcSize"] = round(widthFinded, 2), round(heightFinded, 2)
                        res["calcError"] = round(widthFinded - widthMm, 2), round(heightFinded - heightMm, 2)
                        res["info"] = "识别成功,13边通过一边推测另外一边"
                        useImage = boardColor.copy()
                        cv.drawContours(useImage, [np.array(newBox)], -1, colorGreen, 3)
                        image_show("InnerBoardFindedByCalc13", useImage)
                    else:
                        if heightFinded < heightMin:
                            res["result"] = "small"
                            res["info"] = "高度识别尺寸过小,识别尺寸:{},识别误差:{}".format(res["calcSize"], res["calcError"])
                            return res
                        if heightFinded > heightMax:
                            res["result"] = "big"
                            res["info"] = "高度识别尺寸过大,识别尺寸:{},识别误差:{}".format(res["calcSize"], res["calcError"])
                            return res
                # 再计算一次有没有错误的边缘信息,主要是不能太靠近物料的边缘
                innerLine1 = [leftTop, rightTop]
                innerLine2 = [rightTop, rightBottom]
                innerLine3 = [rightBottom, leftBottom]
                innerLine4 = [leftBottom, leftTop]
                offsetTop = get_two_line_distance(innerLine1, outterLine1) / cp.mm2pix
                offsetRight = get_two_line_distance(innerLine2, outterLine2) / cp.mm2pix
                offsetBottom = get_two_line_distance(innerLine3, outterLine3) / cp.mm2pix
                offsetLeft = get_two_line_distance(innerLine4, outterLine4) / cp.mm2pix
                if min(offsetTop, offsetRight, offsetBottom, offsetLeft) < 6:
                    res["info"] = "识别的内框太靠近物料边缘:({:.2f},{:.2f},{:.2f},{:.2f})".format(offsetTop, offsetRight, offsetBottom, offsetLeft)
                    res["calcSize"] = round(widthFinded, 2), round(heightFinded, 2)
                    res["calcError"] = round(widthFinded - widthMm, 2), round(heightFinded - heightMm, 2)
                    return res
                boxFinded = res["box"]
                if boardPos == "middle":
                    middleBoxPoints = [(p[0], p[1] + int(totalBoard.shape[0] * middleBoxSlice[0])) for p in boxFinded]
                    isOverLap1 = check_two_box_is_overlap(upBox, middleBoxPoints)
                    isOverLap2 = check_two_box_is_overlap(middleBoxPoints, downBox)
                    if isOverLap1 or isOverLap2:
                        totalBoardColor = cv.cvtColor(totalBoard, cv.COLOR_GRAY2BGR)
                        cv.drawContours(totalBoardColor, [np.array(upBox), np.array([middleBoxPoints]), np.array(downBox)], -1, colorGreen, 3)
                        image_show("BoardOverLap", totalBoardColor)
                        res["result"] = "error"
                        res["info"] = "上下框出现叠板,识别失败~"
                        return res
            if resByExtendFlag:
                res["result"] = "okByExtend"
            else:
                res["result"] = "ok"
                res["info"] = "识别成功!"
            return res
    except Exception as e:
        errorInfo = "程序出错: in check_inner_board_3p()  error: {}".format(str(e))
        print(errorInfo)
        res["result"] = "error"
        res["info"] = errorInfo
        return res


def get_inner_board_info_3p(board, jointLine1, jointLine2, width, height, calcThresBig, calcThresSmall, boardPos, isFirstCheck=False,
                            isSizeCheck=False, upBox=None, downBox=None, offset=None, totalBoard=None):
    """
    获取内板信息,三拼板获取内板信息
    :param board:
    :param jointLine1:
    :param jointLine2:
    :param width:
    :param height:
    :param calcThresBig:
    :param calcThresSmall:
    :param boardPos:
    :param isFirstCheck:
    :param isSizeCheck:
    :param upBox:
    :param downBox:
    :param offset:
    :param totalBoard:
    :return:
    """
    boardColor = cv.cvtColor(board.copy(), cv.COLOR_GRAY2BGR)
    sizeOkByExtendRes = []
    sizeDifRes = []
    sizeOkRes = []
    calcArgs = calcArgsNormal
    print("in get_inner_board_info_3p() isFirstCheck = {}".format(isFirstCheck))

    for tryTimes in range(tryBeginIndex, len(calcArgs.keys()) + 1):
        cv.destroyAllWindows()
        gaussianR, squareR, dilateKernel, dilateTimes, erodeTimes, thresOffsetList, scharrRate = calcArgs.get(str(tryTimes))
        print("第{}次计算,计算参数:高斯半径:{},方差核:{},膨胀腐蚀核:{},膨胀腐蚀次数:{},腐蚀膨胀次数:{},阈值offset:{},scharr比例:{}".format(
            tryTimes, gaussianR, squareR, dilateKernel, dilateTimes, erodeTimes, thresOffsetList, scharrRate))

        if len(gaussianR) == 1:
            if gaussianR[0] == 0:
                blurred = board.copy()
            else:
                blurred = cv.GaussianBlur(board, (0, 0), gaussianR[0])
        else:
            d, colorSigma = gaussianR
            spaceSigma = int(d / 2)
            blurred = cv.bilateralFilter(board, d, colorSigma, spaceSigma)

        if scharrRate == 0:
            scharrXY = blurred.copy()
        else:
            scharrX = cv.Scharr(blurred, cv.CV_64F, 1, 0)
            scharrY = cv.Scharr(blurred, cv.CV_64F, 0, 1)
            scharrX = cv.convertScaleAbs(scharrX)
            scharrY = cv.convertScaleAbs(scharrY)
            scharrXY = cv.addWeighted(scharrX, scharrRate, scharrY, scharrRate, 0)
            scharrXY = cv.convertScaleAbs(scharrXY)
            scharrXY = cv.bitwise_and(scharrXY, jointLine1)
        image_show("ScharrXY", scharrXY)
        img32 = np.float32(scharrXY)
        square1 = cv.blur(np.multiply(img32, img32), (squareR, squareR))
        square2 = np.multiply(cv.blur(img32, (squareR, squareR)), cv.blur(img32, (squareR, squareR)))
        squareDif32 = np.subtract(square1, square2)
        squareDif = squareDif32.copy()
        np.clip(squareDif32, 0, 255, out=squareDif)
        squareDif = squareDif.astype("uint8")
        image_show("SquareDif", squareDif)

        # 进行膨胀腐蚀,分割图像
        contourImg = squareDif.copy()
        kernelUsed = cv.getStructuringElement(cv.MORPH_RECT, (dilateKernel, dilateKernel))
        contourImg = cv.dilate(contourImg, kernelUsed, iterations=dilateTimes)
        contourImg = cv.erode(contourImg, kernelUsed, iterations=dilateTimes)
        image_show("squareDifDilateErode", contourImg)

        squareDifErode = contourImg.copy()
        for index, thresOffset in enumerate(thresOffsetList):
            cv.destroyAllWindows()
            image_show("squareDifDilateErode", squareDifErode)
            # 根据阈值进行分割
            centerX, centerY = int(squareDifErode.shape[1] / 2), int(squareDifErode.shape[0] / 2)
            yChoosePos = int(0.1 * squareDifErode.shape[0])
            xChoosePos = int(0.1 * squareDifErode.shape[1])
            thresUsed = squareDifErode[centerY - yChoosePos:centerY + yChoosePos, centerX - xChoosePos:centerX + xChoosePos]
            chooseRoiThres = int(np.mean(thresUsed))
            thresUsedReal = chooseRoiThres + thresOffset
            print("第 {} 个阈值,使用的实际阈值: {},参考的中心区域亮度值: {},thresOffset:{}".format(index + 1, thresUsedReal, chooseRoiThres, thresOffset))
            _, contourImg = cv.threshold(squareDifErode, thresUsedReal, 255, cv.THRESH_BINARY)

            # 处理图像拼接处,如果不是通过scharrXY获取的梯度图像
            if scharrRate == 0:
                contourImg = cv.subtract(contourImg, jointLine2)

            # 进行泛洪填充
            mask = np.zeros((contourImg.shape[0] + 2, contourImg.shape[1] + 2), dtype=np.uint8)
            if contourImg[contourImg.shape[0] // 2, contourImg.shape[1] // 2] > 150:
                cv.floodFill(contourImg, mask, (contourImg.shape[1] // 3, contourImg.shape[0] // 3), 150)
            else:
                cv.floodFill(contourImg, mask, (contourImg.shape[1] // 2, contourImg.shape[0] // 2), 150)

            floodFill = np.zeros(contourImg.shape, dtype=np.uint8)
            floodFill[contourImg == 150] = 250
            image_show("FloodFill", floodFill)

            if len(gaussianR) == 1 and gaussianR[0] >= 10:
                innerLine = True
            else:
                innerLine = False

            if tryTimes == 5:
                extendMiddle = True
            else:
                extendMiddle = False

            # 进行腐蚀膨胀,去除掉边界的噪点
            floodFill = cv.erode(floodFill, kernelUsed, iterations=erodeTimes)
            floodFill = cv.dilate(floodFill, kernelUsed, iterations=erodeTimes)
            image_show("FloodFillErodeDilate", floodFill)
            res = check_inner_board_3p(floodFill, width, height, calcThresBig, calcThresSmall, boardColor, boardPos, upBox, downBox,
                                       innerLine, extendMiddle, isFirstCheck, offset, totalBoard)
            print("计算结果:{},{},识别尺寸:{},{},误差:{}".format(res["result"], res["info"], res["calcSize"],
                                                       (int(res["calcSize"][0] * cp.mm2pix), int(res["calcSize"][1] * cp.mm2pix)), res["calcError"]))
            if res["result"] == "ok":
                sizeOkRes.append(res)
                calcSize = res["calcSize"]
                calcError = res["calcError"]
                if get_sum_abs(calcError) < 7 and not isSizeCheck:
                    print("返回的ok结果是: 算子编号和亮度阈值:({},{}),尺寸:{},{},误差:{}".format(
                        tryTimes, thresOffset, calcSize, (int(calcSize[0] * cp.mm2pix), int(calcSize[1] * cp.mm2pix)), calcError))
                    return "ok", res["info"], res["box"]
                continue
            elif res["result"] == "okByExtend":
                if isSizeCheck:
                    sizeOkRes.append(res)
                else:
                    sizeOkByExtendRes.append(res)
                continue
            elif res["result"] != "error":
                sizeDifRes.append(res)
                if res["result"] == "big" and not innerLine and not extendMiddle:
                    break
                if res["result"] == "small":
                    continue
                continue
    else:
        # 最外层循环结束以后
        if isSizeCheck:
            sizeList = []
            boxList = []
            if len(sizeOkRes) >= 1:
                resOkSorted = sorted(sizeOkRes, key=lambda x: get_sum_abs(x["calcError"]))
                for res in resOkSorted:
                    sizeList.append(res["calcSize"])
                    boxList.append(res["box"])
                return "ok", sizeList, boxList

            if len(sizeDifRes) >= 1:
                resSizeDifSorted = sorted(sizeDifRes, key=lambda x: get_sum_abs(x["calcError"]))
                for res in resSizeDifSorted:
                    sizeList.append(res["calcSize"])
                    boxList.append(res["box"])
                return "sizeDif", sizeList, boxList
            else:
                return "error", "内板寻找失败", None
        else:
            if len(sizeOkRes) >= 1:
                resOkSorted = sorted(sizeOkRes, key=lambda x: get_sum_abs(x["calcError"]))
                res = resOkSorted[0]
                print("返回的ok结果是:尺寸:{},{},误差:{}".format(
                    res["calcSize"], (int(res["calcSize"][0] * cp.mm2pix), int(res["calcSize"][1] * cp.mm2pix)), res["calcError"]))
                return "ok", res["info"], res["box"]

            if len(sizeOkByExtendRes) >= 1:
                resOkSorted = sorted(sizeOkByExtendRes, key=lambda x: get_sum_abs(x["calcError"]))
                res = resOkSorted[0]
                print("返回的ok结果是:尺寸:{},{},误差:{}".format(
                    res["calcError"], (int(res["calcSize"][0] * cp.mm2pix), int(res["calcSize"][1] * cp.mm2pix)), res["calcError"]))
                return "ok", res["info"], res["box"]

            if len(sizeDifRes) >= 1:
                resDifSorted = sorted(sizeDifRes, key=lambda x: get_sum_abs(x["calcError"]))
                res = resDifSorted[0]
                return "sizeDif", res["info"], res["box"]
            else:
                return "error", "找内板失败", None


def get_size_check_result_3p(image, width, height, calcThresBig, totalBoardBox, totalBoard):
    """
    3拼板获取尺寸确认的结果
    :param image:
    :param width:
    :param height:
    :param calcThresBig:
    :param totalBoardBox:
    :param totalBoard:
    :return:
    """
    print("in get_size_check_result_3p()")
    if image is None:
        return "error", None, None, None

    jointLineMask1 = np.ones(image.shape, dtype=np.uint8) * 255
    jointLineMask1[:, cp.middleJointPos - jointLineExtend:cp.middleJointPos + jointLineExtend] = 0
    jointLineMaskNoAngle1, _ = get_board_without_angle_3(jointLineMask1, totalBoardBox)

    jointLineMask2 = np.zeros(image.shape, dtype=np.uint8)
    jointLineMask2[:, cp.middleJointPos - jointLineExtend:cp.middleJointPos + jointLineExtend] = 255
    jointLineMaskNoAngle2, _ = get_board_without_angle_3(jointLineMask2, totalBoardBox)
    cv.destroyAllWindows()
    image_show("TotalBoard", totalBoard)
    _, h = totalBoardBox[1]
    upBoard = totalBoard.copy()[:int(h * upBoxSlice), :]
    upBoardColor = cv.cvtColor(upBoard, cv.COLOR_GRAY2BGR)
    upJointLine1 = jointLineMaskNoAngle1.copy()[:int(h * upBoxSlice), :]
    upJointLine2 = jointLineMaskNoAngle2.copy()[:int(h * upBoxSlice), :]

    upRes, upSizes, upBoxes = get_inner_board_info_3p(upBoard, upJointLine1, upJointLine2, width, height, calcThresBig, calcThresBig, "up",
                                                      isFirstCheck=True, isSizeCheck=True, upBox=None, downBox=None,
                                                      offset=None, totalBoard=totalBoard)
    upBoardResList = []
    upSizeResList = []
    if upRes != "error":
        for index, upBox in enumerate(upBoxes):
            if upBox is not None:
                upBoardRes = upBoardColor.copy()
                cv.drawContours(upBoardRes, [np.array(upBox)], -1, colorGreen, 3)
                centerX, centerY = upBoard.shape[1] // 2, upBoard.shape[0] // 2
                cv.putText(upBoardRes, "{}".format(index + 1), (centerX - 8, centerY), cv.FONT_HERSHEY_COMPLEX, 10, colorBlue, 5)
                image_show("upBoardRes", upBoardRes)
                upBoardResList.append(upBoardRes)
                upSizeResList.append(upSizes[index])
        return "ok", upSizeResList, upBoardResList, upBoardColor
    else:
        return "error", "内板识别出错", None, upBoardColor


def get_boxes_3p(image, width, height, calcThresBig, calcThresSmall, totalBoardBox, totalBoard, upLineOffset,
                middleLineOffset, downLineOffset, isFirstBoard):
    """
    三拼板获取内板的逻辑
    :param image:
    :param width:
    :param height:
    :param calcThresBig:
    :param calcThresSmall:
    :param totalBoardBox:
    :param totalBoard:
    :param upLineOffset:
    :param middleLineOffset:
    :param downLineOffset:
    :param isFirstBoard:
    :return:
    """
    print("in get_boxes_3p() isFirstBoard: {}".format(isFirstBoard))
    w, h = totalBoardBox[1]
    totalBoardColor = cv.cvtColor(totalBoard.copy(), cv.COLOR_GRAY2BGR)
    jointLineMask1 = np.ones(image.shape, dtype=np.uint8) * 255
    jointLineMask1[:, cp.middleJointPos - jointLineExtend:cp.middleJointPos + jointLineExtend] = 0  # 中缝拼接处的处理,使用梯度scharr的时候
    jointLineMaskNoAngle1, _ = get_board_without_angle_3(jointLineMask1, totalBoardBox)
    jointLineMask2 = np.zeros(image.shape, dtype=np.uint8)
    jointLineMask2[:, cp.middleJointPos - jointLineExtend:cp.middleJointPos + jointLineExtend] = 255  # 中缝拼接处的处理,直接方差
    jointLineMaskNoAngle2, _ = get_board_without_angle_3(jointLineMask2, totalBoardBox)
    cv.destroyAllWindows()
    image_show("TotalBoard", totalBoard)
    upBoard = totalBoard.copy()[:int(h * upBoxSlice), :]
    middleBoard = totalBoard.copy()[int(h * middleBoxSlice[0]):int(h * middleBoxSlice[1]), :]
    downBoard = totalBoard.copy()[int(h * downBoxSlice):, :]

    upJointLine1 = jointLineMaskNoAngle1.copy()[:int(h * upBoxSlice), :]
    middleJointLine1 = jointLineMaskNoAngle1.copy()[int(h * middleBoxSlice[0]):int(h * middleBoxSlice[1]), :]
    downJointLine1 = jointLineMaskNoAngle1.copy()[int(h * downBoxSlice):, :]

    upJointLine2 = jointLineMaskNoAngle2.copy()[:int(h * upBoxSlice), :]
    middleJointLine2 = jointLineMaskNoAngle2.copy()[int(h * middleBoxSlice[0]):int(h * middleBoxSlice[1]), :]
    downJointLine2 = jointLineMaskNoAngle2.copy()[int(h * downBoxSlice):, :]
    boxesRes = []
    upRes, upInfo, upBox = get_inner_board_info_3p(upBoard, upJointLine1, upJointLine2, width, height, calcThresBig, calcThresSmall, "up",
                                                   isFirstBoard, isSizeCheck=False, upBox=None, downBox=None,
                                                   offset=upLineOffset, totalBoard=totalBoard)
    if upRes != "ok":
        return False, upInfo, boxesRes

    downRes, downInfo, downBox = get_inner_board_info_3p(downBoard, downJointLine1, downJointLine2, width, height, calcThresBig, calcThresSmall,
                                                         "down", isFirstBoard, isSizeCheck=False, upBox=None, downBox=None,
                                                         offset=downLineOffset, totalBoard=totalBoard)
    if downRes != "ok":
        return False, downInfo, boxesRes
    else:
        downBox = [(p[0], p[1] + int(h * downBoxSlice)) for p in downBox]

    middleRes, middleInfo, middleBox = get_inner_board_info_3p(middleBoard, middleJointLine1, middleJointLine2, width, height, calcThresBig,
                                                               calcThresSmall,
                                                               "middle", isFirstBoard, isSizeCheck=False, upBox=upBox, downBox=downBox,
                                                               offset=middleLineOffset, totalBoard=totalBoard)
    if middleRes != "ok":
        return False, middleInfo, boxesRes

    if upRes == "ok" and downRes == "ok" and middleRes == "ok":
        middleBoxPoints = [(p[0], p[1] + int(h * middleBoxSlice[0])) for p in middleBox]
        middleBox = middleBoxPoints
        cv.drawContours(totalBoardColor, [np.array(upBox), np.array(middleBox), np.array(downBox)], -1, colorGreen, 3)
        image_show("ThreeBoxesFinded", totalBoardColor)
        boxesRes = [upBox, middleBox, downBox]
        return True, "识别成功!", boxesRes
    else:
        return False, upInfo + middleInfo + downInfo, boxesRes


def get_lines_with_boxes_3p(image, totalBoard, totalBoardBox, totalBoardThres, boxesRes, transMtx, topRemain, leftRemain,
                           bottomRemain, rightRemain, totalBoardOffset):
    """
    根据识别出来的内框,获取切线,3拼板
    :param image:
    :param totalBoard:
    :param totalBoardBox:
    :param totalBoardThres:
    :param boxesRes:
    :param transMtx:
    :param topRemain:
    :param leftRemain:
    :param bottomRemain:
    :param rightRemain:
    :param totalBoardOffset:
    :return:
    """
    if len(image.shape) >= 3:
        image = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
    imageColor = cv.cvtColor(image,cv.COLOR_GRAY2BGR)
    (cx,cy),(w,h),totalBoardAngle = totalBoardBox
    upBox,middleBox,downBox = boxesRes

    upLeftTop, upRightTop, upRightBottom, upLeftBottom = upBox
    middleLeftTop, middleRightTop, middleRightBottom, middleLeftBottom = middleBox
    downLeftTop, downRightTop, downRightBottom, downLeftBottom = downBox

    leftCutLineK = get_linear_fit_k_vertical(np.array([upLeftTop, upLeftBottom,
                                                       middleLeftTop, middleLeftBottom,
                                                       downLeftTop, downLeftBottom]))
    if leftCutLineK is None:
        leftCutLineB = min(upLeftTop[0], upLeftBottom[0], middleLeftTop[0],
                           middleLeftBottom[0], downLeftTop[0], downLeftBottom[0]) - leftRemain
    else:
        upLeftTopX = upLeftTop[1] - (upLeftTop[0] - leftRemain) * leftCutLineK
        upLeftBottomX = upLeftBottom[1] - (upLeftBottom[0] - leftRemain) * leftCutLineK
        middleLeftTopX = middleLeftTop[1] - (middleLeftTop[0] - leftRemain) * leftCutLineK
        middleLeftBottomX = middleLeftBottom[1] - (middleLeftBottom[0] - leftRemain) * leftCutLineK
        downLeftTopX = downLeftTop[1] - (downLeftTop[0] - leftRemain) * leftCutLineK
        downLeftBottomX = downLeftBottom[1] - (downLeftBottom[0] - leftRemain) * leftCutLineK

        if leftCutLineK > 0:  # 当k大于0的时候,b越大,越靠左
            leftCutLineB = max(upLeftTopX, upLeftBottomX, middleLeftTopX, middleLeftBottomX, downLeftTopX, downLeftBottomX)
        else:
            leftCutLineB = min(upLeftTopX, upLeftBottomX, middleLeftTopX, middleLeftBottomX, downLeftTopX, downLeftBottomX)

    rightCutLineK = get_linear_fit_k_vertical(np.array([upRightTop, upRightBottom, middleRightTop,
                                                        middleRightBottom, downRightTop, downRightBottom]))
    if rightCutLineK is None:
        rightCutLineB = max(upRightTop[0], upRightBottom[0], middleRightTop[0], middleRightBottom[0],
                            downRightTop[0], downRightBottom[0]) + rightRemain
    else:
        upRightTopX = upRightTop[1] - (upRightTop[0] + rightRemain) * rightCutLineK
        upRightBottomX = upRightBottom[1] - (upRightBottom[0] + rightRemain) * rightCutLineK
        middleRightTopX = middleRightTop[1] - (middleRightTop[0] + rightRemain) * rightCutLineK
        middleRightBottomX = middleRightBottom[1] - (middleRightBottom[0] + rightRemain) * rightCutLineK
        downRightTopX = downRightTop[1] - (downRightTop[0] + rightRemain) * rightCutLineK
        downRightBottomX = downRightBottom[1] - (downRightBottom[0] + rightRemain) * rightCutLineK
        if rightCutLineK > 0:  # 当k大于0的时候,b越大,越靠左
            rightCutLineB = min(upRightTopX, upRightBottomX, middleRightTopX, middleRightBottomX,
                                downRightTopX, downRightBottomX)
        else:
            rightCutLineB = max(upRightTopX, upRightBottomX, middleRightTopX, middleRightBottomX,
                                downRightTopX, downRightBottomX)

    topCutLineK = get_line_k_and_b(upLeftTop, upRightTop)[0]
    if topCutLineK is None:
        cv.destroyAllWindows()
        return False, None, None
    else:
        topCutLineB = topCutLineK * -1 * (upLeftTop[0]) + (upLeftTop[1] - topRemain)

    bottomCutLineK = get_line_k_and_b(downLeftBottom, downRightBottom)[0]
    if bottomCutLineK is None:
        # 垂直，一定是异常
        cv.destroyAllWindows()
        return False, None, None, None
    else:
        bottomCutLineB = bottomCutLineK * -1 * (downLeftBottom[0]) + downLeftBottom[1] + bottomRemain

    # 先分别求出来两个中缝的角度,firstMiddleK,secondMiddleK,然后两个中缝求一个角平分线,按照这个角平分线搞中缝的角度
    firstMiddleK, firstMiddleB = get_middle_cut_line(upLeftBottom, upRightBottom, middleLeftTop, middleRightTop)
    secondMiddleK, secondMiddleB = get_middle_cut_line(middleLeftBottom, middleRightBottom, downLeftTop, downRightTop)
    # 求中点,两个中点y值,一个是上框和中框的中点的中点,一个是中框和下框的中点的y值
    firstMiddleY = (get_two_points_middle(upLeftBottom, upRightBottom)[1] +
                    get_two_points_middle(middleLeftTop, middleRightTop)[1]) / 2
    secondMiddleY = (get_two_points_middle(middleLeftBottom, middleRightBottom)[1] +
                     get_two_points_middle(downLeftTop, downRightTop)[1]) / 2
    firstMiddleLine, secondMiddleLine = get_two_lines_angular_bisector(firstMiddleK, firstMiddleB, secondMiddleK,
                                                                       secondMiddleB, firstMiddleY, secondMiddleY)
    firstMiddleK, firstMiddleB = firstMiddleLine
    secondMiddleK, secondMiddleB = secondMiddleLine

    boardLeftTop = [0, 0]
    boardRightTop = [w, 0]
    boardLeftBottom = [0, h]
    boardRightBottom = [w, h]
    findEdgeExtend = int(7 * cp.mm2pix)  # 找边缘的时候延长10个mm
    totalBoardExtendForFindEdge, _ = get_board_without_angle_3(image, totalBoardBox, findEdgeExtend)
    totalBoardThresForFindEdge, _ = get_board_without_angle_3(totalBoardThres, totalBoardBox, findEdgeExtend)

    leftTopY = upLeftTop[1] - topRemain
    rightTopY = upRightTop[1] - topRemain
    if leftTopY < 0 or rightTopY < 0:
        topRemain = 0
    leftBottomY = downLeftBottom[1] + bottomRemain
    rightBottomY = downRightBottom[1] + bottomRemain
    if leftBottomY > totalBoard.shape[0] or rightBottomY > totalBoard.shape[0]:
        bottomRemain = 0

    if topRemain == 0:
        topLineK, topLineB = find_first_edge_line(totalBoardExtendForFindEdge, totalBoardThresForFindEdge,findEdgeExtend)
        if topLineK is not None:
            topCutLineK, topCutLineB = topLineK, topLineB
        else:
            topCutLineK, topCutLineB = get_line_k_and_b(boardLeftTop, boardRightTop)

    if bottomRemain == 0:
        bottomLineK, bottomLineB = find_third_edge_line(totalBoardExtendForFindEdge, totalBoardThresForFindEdge,findEdgeExtend)
        if bottomLineK is not None:
            bottomCutLineK, bottomCutLineB = bottomLineK, bottomLineB
        else:
            bottomCutLineK, bottomCutLineB = get_line_k_and_b(boardLeftBottom, boardRightBottom)
    if leftRemain == 0:
        leftCutLineK, leftCutLineB = get_line_k_and_b(boardLeftBottom, boardLeftTop)
    if rightRemain == 0:
        rightCutLineK, rightCutLineB = get_line_k_and_b(boardRightTop, boardRightBottom)

    # 求所有线的交点
    leftTopCross = get_two_lines_intersection(topCutLineK, topCutLineB, leftCutLineK, leftCutLineB)
    rightTopCross = get_two_lines_intersection(topCutLineK, topCutLineB, rightCutLineK, rightCutLineB)
    leftFirstMiddleCross = get_two_lines_intersection(firstMiddleK, firstMiddleB, leftCutLineK, leftCutLineB)
    rightFirstMiddleCross = get_two_lines_intersection(firstMiddleK, firstMiddleB, rightCutLineK, rightCutLineB)
    leftSecondMiddleCross = get_two_lines_intersection(secondMiddleK, secondMiddleB, leftCutLineK, leftCutLineB)
    rightSecondMiddleCross = get_two_lines_intersection(secondMiddleK, secondMiddleB, rightCutLineK, rightCutLineB)
    leftBottomCross = get_two_lines_intersection(bottomCutLineK, bottomCutLineB, leftCutLineK, leftCutLineB)
    rightBottomCross = get_two_lines_intersection(bottomCutLineK, bottomCutLineB, rightCutLineK, rightCutLineB)

    extend = int(8 * cp.mm2pix)
    extendLeftRight = int(15 * cp.mm2pix)

    topCutLeftPoint = [- extend, topCutLineK * (- extend) + topCutLineB]
    topCutRightPoint = [extend + w, topCutLineK * (extend + w) + topCutLineB]

    bottomCutRightPoint = [w + extend, bottomCutLineK * (w + extend) + bottomCutLineB]
    bottomCutLeftPoint = [- extend, bottomCutLineK * (- extend) + bottomCutLineB]

    if leftCutLineK is None:
        # 按照整个物料的高度去延长切线
        # leftCutLineBottom = [leftCutLineB, h + extendLeftRight]
        # leftCutLineTop = [leftCutLineB, -extendLeftRight]
        # 按照交点延长去切
        leftCutLineBottom = [leftCutLineB, leftBottomCross[1] + extendLeftRight]
        leftCutLineTop = [leftCutLineB, leftTopCross[1] - extendLeftRight]
    elif leftCutLineK != 0:
        # 按照整个物料的高度去延长切线
        # leftCutLineBottom = [((h + extendLeftRight) - leftCutLineB) / leftCutLineK, h + extendLeftRight]
        # leftCutLineTop = [(- extendLeftRight - leftCutLineB) / leftCutLineK, - extendLeftRight]
        # 按照和1,3刀的交点延长切线
        leftCutLineBottom = [((leftBottomCross[1] + extendLeftRight) - leftCutLineB) / leftCutLineK,
                             leftBottomCross[1] + extendLeftRight]
        leftCutLineTop = [(leftTopCross[1] - extendLeftRight - leftCutLineB) / leftCutLineK,
                          leftTopCross[1] - extendLeftRight]
    else:
        cv.destroyAllWindows()
        return False, None, None, None

    if rightCutLineK is None:
        # 按照整个物料的高度去延长切线
        # rightCutLineTop = [rightCutLineB, - extendLeftRight]
        # rightCutLineBottom = [rightCutLineB, h + extendLeftRight]
        # 按照和13刀的交点去延长切线
        rightCutLineTop = [rightCutLineB, rightTopCross[1] - extendLeftRight]
        rightCutLineBottom = [rightCutLineB, rightBottomCross[1] + extendLeftRight]
    elif rightCutLineK != 0:
        # 按照整个物料的高度去延长切线
        # rightCutLineTop = [((- extendLeftRight) - rightCutLineB) / rightCutLineK,
        #                    - extendLeftRight]
        # rightCutLineBottom = [((h + extendLeftRight) - rightCutLineB) / rightCutLineK,
        #                       h + extendLeftRight]
        # 按照和13刀的交点去延长切线
        rightCutLineTop = [((rightTopCross[1] - extendLeftRight) - rightCutLineB) / rightCutLineK,
                           rightTopCross[1] - extendLeftRight]
        rightCutLineBottom = [((rightBottomCross[1] + extendLeftRight) - rightCutLineB) / rightCutLineK,
                              rightBottomCross[1] + extendLeftRight]
    else:
        cv.destroyAllWindows()
        return False, None, None, None
    rotatedCenter = (cx, cy)
    M = cv.getRotationMatrix2D(rotatedCenter, -totalBoardAngle, 1)
    centerOffset = totalBoardOffset

    boardLeftTopBig = np.dot(M, [boardLeftTop[0] + centerOffset[0], boardLeftTop[1] + centerOffset[1], 1])
    boardRightTopBig = np.dot(M, [boardRightTop[0] + centerOffset[0], boardRightTop[1] + centerOffset[1], 1])
    boardRightBottomBig = np.dot(M, [boardRightBottom[0] + centerOffset[0], boardRightBottom[1] + centerOffset[1], 1])
    boardLeftBottomBig = np.dot(M, [boardLeftBottom[0] + centerOffset[0], boardLeftBottom[1] + centerOffset[1], 1])

    topCutLeftPointBig = np.dot(M, [topCutLeftPoint[0] + centerOffset[0], topCutLeftPoint[1] + centerOffset[1], 1])
    topCutRightPointBig = np.dot(M, [topCutRightPoint[0] + centerOffset[0], topCutRightPoint[1] + centerOffset[1], 1])
    bottomCutRightPointBig = np.dot(M, [bottomCutRightPoint[0] + centerOffset[0], bottomCutRightPoint[1] + centerOffset[1], 1])
    bottomCutLeftPointBig = np.dot(M, [bottomCutLeftPoint[0] + centerOffset[0], bottomCutLeftPoint[1] + centerOffset[1], 1])
    leftCutLineBottomBig = np.dot(M, [leftCutLineBottom[0] + centerOffset[0], leftCutLineBottom[1] + centerOffset[1], 1])
    leftCutLineTopBig = np.dot(M, [leftCutLineTop[0] + centerOffset[0], leftCutLineTop[1] + centerOffset[1], 1])
    rightCutLineTopBig = np.dot(M, [rightCutLineTop[0] + centerOffset[0], rightCutLineTop[1] + centerOffset[1], 1])
    rightCutLineBottomBig = np.dot(M, [rightCutLineBottom[0] + centerOffset[0], rightCutLineBottom[1] + centerOffset[1], 1])

    firstMiddleCutLineLeftBig = np.dot(M, [leftFirstMiddleCross[0] + centerOffset[0],
                                           leftFirstMiddleCross[1] + centerOffset[1], 1])
    firstMiddleCutLineRightBig = np.dot(M, [rightFirstMiddleCross[0] + centerOffset[0],
                                            rightFirstMiddleCross[1] + centerOffset[1], 1])
    secondMiddleCutLineLeftBig = np.dot(M, [leftSecondMiddleCross[0] + centerOffset[0],
                                            leftSecondMiddleCross[1] + centerOffset[1], 1])
    secondMiddleCutLineRightBig = np.dot(M, [rightSecondMiddleCross[0] + centerOffset[0],
                                             rightSecondMiddleCross[1] + centerOffset[1], 1])

    # 重新将端点定位到大图上去
    upLeftBottom = np.dot(M, [upLeftBottom[0] + centerOffset[0], upLeftBottom[1] + centerOffset[1], 1])
    upRightBottom = np.dot(M, [upRightBottom[0] + centerOffset[0], upRightBottom[1] + centerOffset[1], 1])
    upLeftTop = np.dot(M, [upLeftTop[0] + centerOffset[0], upLeftTop[1] + centerOffset[1], 1])
    upRightTop = np.dot(M, [upRightTop[0] + centerOffset[0], upRightTop[1] + centerOffset[1], 1])

    middleLeftBottom = np.dot(M, [middleLeftBottom[0] + centerOffset[0], middleLeftBottom[1] + centerOffset[1], 1])
    middleRightBottom = np.dot(M, [middleRightBottom[0] + centerOffset[0], middleRightBottom[1] + centerOffset[1], 1])
    middleLeftTop = np.dot(M, [middleLeftTop[0] + centerOffset[0], middleLeftTop[1] + centerOffset[1], 1])
    middleRightTop = np.dot(M, [middleRightTop[0] + centerOffset[0], middleRightTop[1] + centerOffset[1], 1])

    downLeftTop = np.dot(M, [downLeftTop[0] + centerOffset[0], downLeftTop[1] + centerOffset[1], 1])
    downLeftBottom = np.dot(M, [downLeftBottom[0] + centerOffset[0], downLeftBottom[1] + centerOffset[1], 1])
    downRightTop = np.dot(M, [downRightTop[0] + centerOffset[0], downRightTop[1] + centerOffset[1], 1])
    downRightBottom = np.dot(M, [downRightBottom[0] + centerOffset[0], downRightBottom[1] + centerOffset[1], 1])

    # 画出内框
    cv.line(imageColor, (int(upLeftBottom[0]), int(upLeftBottom[1])), (int(upRightBottom[0]), int(upRightBottom[1])),
            colorGreen, 3)
    cv.line(imageColor, (int(upLeftBottom[0]), int(upLeftBottom[1])), (int(upLeftTop[0]), int(upLeftTop[1])), colorGreen,
            3)
    cv.line(imageColor, (int(upRightBottom[0]), int(upRightBottom[1])), (int(upRightTop[0]), int(upRightTop[1])),
            colorGreen, 3)
    cv.line(imageColor, (int(upLeftTop[0]), int(upLeftTop[1])), (int(upRightTop[0]), int(upRightTop[1])), colorGreen, 3)

    cv.line(imageColor, (int(downLeftBottom[0]), int(downLeftBottom[1])),
            (int(downRightBottom[0]), int(downRightBottom[1])), colorGreen, 3)
    cv.line(imageColor, (int(downLeftBottom[0]), int(downLeftBottom[1])), (int(downLeftTop[0]), int(downLeftTop[1])),
            colorGreen, 3)
    cv.line(imageColor, (int(downRightBottom[0]), int(downRightBottom[1])), (int(downRightTop[0]), int(downRightTop[1])),
            colorGreen, 3)
    cv.line(imageColor, (int(downLeftTop[0]), int(downLeftTop[1])), (int(downRightTop[0]), int(downRightTop[1])),
            colorGreen, 3)

    cv.line(imageColor, (int(middleLeftBottom[0]), int(middleLeftBottom[1])),
            (int(middleRightBottom[0]), int(middleRightBottom[1])), colorGreen, 3)
    cv.line(imageColor, (int(middleLeftBottom[0]), int(middleLeftBottom[1])), (int(middleLeftTop[0]), int(middleLeftTop[1])),
            colorGreen, 3)
    cv.line(imageColor, (int(middleRightBottom[0]), int(middleRightBottom[1])), (int(middleRightTop[0]), int(middleRightTop[1])),
            colorGreen, 3)
    cv.line(imageColor, (int(middleLeftTop[0]), int(middleLeftTop[1])), (int(middleRightTop[0]), int(middleRightTop[1])),
            colorGreen, 3)

    # 画出上，下，左，右，中五条切线
    textScale = 3
    textThickness = 8
    cv.line(imageColor, (int(topCutLeftPointBig[0]), int(topCutLeftPointBig[1])),
            (int(topCutRightPointBig[0]), int(topCutRightPointBig[1])), colorRed, 3)
    cv.putText(imageColor, '1', (int((topCutLeftPointBig[0] + topCutRightPointBig[0]) / 2),
                                 int((topCutLeftPointBig[1] + topCutRightPointBig[1]) / 2) - 40),
               cv.FONT_HERSHEY_COMPLEX, textScale, colorRed, textThickness)
    cv.line(imageColor, (int(bottomCutRightPointBig[0]), int(bottomCutRightPointBig[1])),
            (int(bottomCutLeftPointBig[0]), int(bottomCutLeftPointBig[1])), colorRed, 3)
    cv.putText(imageColor, '3', (int((bottomCutRightPointBig[0] + bottomCutLeftPointBig[0]) / 2),
                                 int((bottomCutRightPointBig[1] + bottomCutLeftPointBig[1]) / 2) + 90),
               cv.FONT_HERSHEY_COMPLEX, textScale, colorRed, textThickness)

    cv.line(imageColor, (int(leftCutLineBottomBig[0]), int(leftCutLineBottomBig[1])),
            (int(leftCutLineTopBig[0]), int(leftCutLineTopBig[1])), colorRed, 3)
    cv.putText(imageColor, '2', (int((leftCutLineBottomBig[0] + leftCutLineTopBig[0]) / 2) - 100,
                                 int((leftCutLineBottomBig[1] + leftCutLineTopBig[1]) / 2)),
               cv.FONT_HERSHEY_COMPLEX, textScale, colorRed, textThickness)
    cv.line(imageColor, (int(rightCutLineTopBig[0]), int(rightCutLineTopBig[1])),
            (int(rightCutLineBottomBig[0]), int(rightCutLineBottomBig[1])), colorRed, 3)
    cv.putText(imageColor, '4', (int((rightCutLineTopBig[0] + rightCutLineBottomBig[0]) / 2) + 30,
                                 int((rightCutLineTopBig[1] + rightCutLineBottomBig[1]) / 2)),
               cv.FONT_HERSHEY_COMPLEX, textScale, colorRed, textThickness)
    cv.line(imageColor, (int(firstMiddleCutLineLeftBig[0]), int(firstMiddleCutLineLeftBig[1])),
            (int(firstMiddleCutLineRightBig[0]), int(firstMiddleCutLineRightBig[1])), colorBlue, 3)
    cv.line(imageColor, (int(secondMiddleCutLineLeftBig[0]), int(secondMiddleCutLineLeftBig[1])),
            (int(secondMiddleCutLineRightBig[0]), int(secondMiddleCutLineRightBig[1])), colorBlue, 3)

    # 将所有的点都转换为机械手上的坐标
    topCutLeftPointRobot = pix_pos_to_robot(topCutLeftPointBig, transMtx)
    topCutRightPointRobot = pix_pos_to_robot(topCutRightPointBig, transMtx)
    bottomCutLeftPointRobot = pix_pos_to_robot(bottomCutLeftPointBig, transMtx)
    bottomCutRightPointRobot = pix_pos_to_robot(bottomCutRightPointBig, transMtx)
    leftCutLineBottomRobot = pix_pos_to_robot(leftCutLineBottomBig, transMtx)
    leftCutLineTopRobot = pix_pos_to_robot(leftCutLineTopBig, transMtx)
    rightCutLineTopRobot = pix_pos_to_robot(rightCutLineTopBig, transMtx)
    rightCutLineBottomRobot = pix_pos_to_robot(rightCutLineBottomBig, transMtx)
    firstMiddleCutLineLeftRobot = pix_pos_to_robot(firstMiddleCutLineLeftBig, transMtx)
    firstMiddleCutLineRightRobot = pix_pos_to_robot(firstMiddleCutLineRightBig, transMtx)
    secondMiddleCutLineLeftRobot = pix_pos_to_robot(secondMiddleCutLineLeftBig, transMtx)
    secondMiddleCutLineRightRobot = pix_pos_to_robot(secondMiddleCutLineRightBig, transMtx)

    boardLeftTopRobot = pix_pos_to_robot(boardLeftTopBig, transMtx)
    boardRightTopRobot = pix_pos_to_robot(boardRightTopBig, transMtx)
    boardRightBottomRobot = pix_pos_to_robot(boardRightBottomBig, transMtx)
    boardLeftBottomRobot = pix_pos_to_robot(boardLeftBottomBig, transMtx)

    cutDisTotal = 0
    cutAreaTotal = 0
    if topRemain != 0:
        cutDis = get_two_point_distance(topCutLeftPointRobot, topCutRightPointRobot)
        area = cutDis * (get_two_point_distance(get_two_points_middle(topCutLeftPointRobot, topCutRightPointRobot),
                                  get_two_points_middle(boardLeftTopRobot, boardRightTopRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis
    if leftRemain != 0:
        cutDis = get_two_point_distance(leftCutLineBottomRobot, leftCutLineTopRobot)
        area = cutDis * (get_two_point_distance(get_two_points_middle(leftCutLineBottomRobot, leftCutLineTopRobot),
                                  get_two_points_middle(boardLeftTopRobot, boardLeftBottomRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis

    if bottomRemain != 0:
        cutDis = get_two_point_distance(bottomCutRightPointRobot, bottomCutLeftPointRobot)
        area = cutDis * (get_two_point_distance(get_two_points_middle(bottomCutRightPointRobot, bottomCutLeftPointRobot),
                                  get_two_points_middle(boardLeftBottomRobot, boardRightBottomRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis

    if rightRemain != 0:
        cutDis = get_two_point_distance(rightCutLineTopRobot, rightCutLineBottomRobot)
        area = cutDis * (get_two_point_distance(get_two_points_middle(rightCutLineTopRobot, rightCutLineBottomRobot),
                                  get_two_points_middle(boardRightTopRobot, boardRightBottomRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis

    imageResult,_ = get_board_without_angle_3(imageColor, totalBoardBox, extend=80)
    image_show("resultImage", imageResult)
    # 以裁切机的实际切线为标准，计算前板长，后板长，总长
    # 先算中线中点
    firstLength, secondLength, thirdLength = get_board_length_three([topCutLeftPointRobot, topCutRightPointRobot],
                                                                    [firstMiddleCutLineLeftRobot, firstMiddleCutLineRightRobot],
                                                                    [secondMiddleCutLineLeftRobot, secondMiddleCutLineRightRobot],
                                                                    [bottomCutLeftPointRobot, bottomCutRightPointRobot])

    topFirstMiddleAngle = get_two_line_angle((firstMiddleCutLineRightRobot, firstMiddleCutLineLeftRobot),
                                             (topCutRightPointRobot, topCutLeftPointRobot))
    bottomFirstMiddleAngle = get_two_line_angle((firstMiddleCutLineRightRobot, firstMiddleCutLineLeftRobot),
                                                (bottomCutRightPointRobot, bottomCutLeftPointRobot))
    twoMiddleAngle = get_two_line_angle((secondMiddleCutLineRightRobot, secondMiddleCutLineLeftRobot),
                                        (firstMiddleCutLineRightRobot, firstMiddleCutLineLeftRobot))
    bottomSecondMiddleAngle = get_two_line_angle((secondMiddleCutLineRightRobot, secondMiddleCutLineLeftRobot),
                                                 (bottomCutRightPointRobot, bottomCutLeftPointRobot))

    # 是否切第一刀
    isFirstCut = True if topRemain != 0 else False
    isThirdCut = True if bottomRemain != 0 else False
    cutLength = [round(cutDisTotal, 5), round(cutAreaTotal, 5)]
    angleList = [topFirstMiddleAngle, bottomFirstMiddleAngle, twoMiddleAngle, bottomSecondMiddleAngle]
    cutWidth = get_two_point_distance(leftCutLineTopRobot,rightCutLineTopRobot)
    print("length:{},{},{},angleList:{},{},{},{}".format(firstLength, secondLength, thirdLength,
                                                         angleList[0], angleList[1], angleList[2], angleList[3]))

    return [topCutLeftPointRobot, topCutRightPointRobot, bottomCutRightPointRobot, bottomCutLeftPointRobot,
            leftCutLineBottomRobot, leftCutLineTopRobot, rightCutLineTopRobot, rightCutLineBottomRobot,
            firstMiddleCutLineLeftRobot, firstMiddleCutLineRightRobot, secondMiddleCutLineLeftRobot, secondMiddleCutLineRightRobot,
            firstLength, secondLength, thirdLength, angleList], imageResult, cutLength, isFirstCut, isThirdCut,cutWidth


if __name__ == '__main__':
    filePath = r"D:\xizhen_01\3pin"
    res, data = db.get_line_cam_check_thres()
    totalHeightMax = data.get("totalHeightMax")
    totalHeightMin = data.get("totalHeightMin")
    boardBreak = False
    calcThresBig = 20
    calcThresSmall = 9
    res1, transMtxData = db.get_trans_mtx_data()
    transMtx = None
    if res1 != "ok":
        errorInfo = "{},标定矩阵获取失败!".format(res1)
        print(errorInfo)
    else:
        transMtx = transMtxData.get("mtx")
    jointNumber = "2"
    remainEdgeMm = [0, 13, 0, 13]
    topRemain, leftRemain, bottomRemain, rightRemain = [int(x * cp.mm2pix) for x in remainEdgeMm]

    keepDir = filePath
    if not os.path.isdir(keepDir):
        keepDir, _ = os.path.split(filePath)

    keepOkPath = os.path.join(keepDir, "ok")
    keepOkResPath = os.path.join(keepDir, "cutlines")
    keepFailPath = os.path.join(keepDir, "fail")
    keepFirstSizeBestRes = os.path.join(keepDir, "first_size_check_best")

    dirList = [keepOkPath, keepOkResPath, keepFailPath, keepFirstSizeBestRes]
    for dirDemo in dirList:
        if not os.path.exists(dirDemo):
            os.mkdir(dirDemo)

    fileNames = []
    if os.path.isfile(filePath):
        filePath, fileName = os.path.split(filePath)
        fileNames.append(fileName)
    else:
        for root, dirs, files in os.walk(filePath):
            if root != filePath:
                continue
            for file in files:
                if file[-4:] != ".bmp":
                    continue
                fileNames.append(file)

    for index, fileName in enumerate(fileNames):
        filePathReal = os.path.join(filePath, fileName)
        srcW, srcH, upLineOffset, middleLineOffset, downLineOffset = get_width_and_height_by_image_name_3p(fileName)
        if srcW is None or srcH is None:
            print("*" * 10 + "第 {} 张图 ({}),图像名称错误,已跳过".format(index + 1, fileName))
        if 0 in upLineOffset or 0 in downLineOffset or 0 in middleLineOffset:
            isFirstBoard = False
        else:
            isFirstBoard = False

        print("*" * 10 + "第 {} 张图 ({})".format(index + 1, fileName) + "*" * 10)
        calcStart = time.time()
        imageSrc = cv.imread(filePathReal, cv.IMREAD_GRAYSCALE)
        totalBoardRes = check_total_board_is_ok(imageSrc, totalHeightMax, totalHeightMin, boardBreak, jointNumber)
        res, hintInfo, totalBoardBox, totalBoardNoAngle, totalBoardOffset, totalBoardThresWithAngle, totalBoardResWithAngle = totalBoardRes
        print("物料检测结果: {}, {}".format(res, hintInfo))
        if isFirstBoard:
            resFirst, boardSizeList, boardResList, upBoard = get_size_check_result_3p(imageSrc, srcW, srcH, calcThresBig, totalBoardBox,
                                                                                      totalBoardNoAngle)
            if resFirst != "error":
                sizeCheckResBest = boardResList[0]
                sizeCheckResBest = get_size_scale_image(sizeCheckResBest, sizeScale=4)
                cv.imwrite(os.path.join(keepFirstSizeBestRes, fileName), sizeCheckResBest)

        res, info, boxesRes = get_boxes_3p(imageSrc, srcW, srcH, calcThresBig, calcThresSmall, totalBoardBox, totalBoardNoAngle,
                                                           upLineOffset, middleLineOffset, downLineOffset, isFirstBoard)
        if res:
            lineRes = get_lines_with_boxes_3p(imageSrc, totalBoardNoAngle, totalBoardBox, totalBoardThresWithAngle,boxesRes, transMtx,
                                              topRemain, leftRemain, bottomRemain, rightRemain, totalBoardOffset)
            cutLines, imageRes, cutDis, isFirstCut, isThirdCut, cutWidth = lineRes
            print("算法耗时: {}".format(time.time() - calcStart))
            os.remove(filePathReal)
            imageRes = get_size_scale_image(imageRes, sizeScale=4)
            cv.imwrite(os.path.join(keepOkResPath, fileName), imageRes)
            cv.imwrite(os.path.join(keepOkPath, fileName), imageSrc)
            print("识别成功!结果:切割面积:{},切割宽度:{},角度长度:{}".format(cutDis, cutWidth, cutLines[-4:]))
            continue
        else:
            print("算法耗时: {}".format(time.time() - calcStart))
            cv.imwrite(os.path.join(keepFailPath, fileName), imageSrc)
            os.remove(filePathReal)
            print("识别失败XXXXXXXXXXXXXXXXXXXXXXXXX")
            continue
